package cn.yuan.data.service.impl;

import cn.common.constant.EntrustConstant;
import cn.common.exception.BusinessException;
import cn.common.utils.UserContextUtils;
import cn.constant.CoinConstant;
import cn.constant.ContractConstant;
import cn.model.*;
import cn.yuan.data.mapper.*;
import cn.yuan.data.product.MatchProducer;
import cn.yuan.data.service.EntrustService;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuan.common.redis.constant.CacheConstants;
import com.yuan.common.redis.lock.RedisDistributedLock;
import com.yuan.common.redis.service.RedisRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class EntrustServiceImpl extends ServiceImpl<EntrustMapper, Entrust>  implements EntrustService {
    public static final ConcurrentHashMap<String, Object> member_entrust = new ConcurrentHashMap<String, Object>();
    @Autowired
    public RedisRepository redisRepository;
    @Autowired
    public PairsMapper pairsMapper;

    @Autowired
    public MemberMapper memberMapper;
    @Autowired
    public BalanceMapper balanceMapper;
    @Autowired
    public EntrustHistoryMapper entrustHistoryMapper;
    @Autowired
    public EntrustMapper entrustMapper;
    @Autowired
    public MatchProducer matchProducer;
    public boolean setEntrust(Entrust entrust){
        String userId = UserContextUtils.getCurrentUserId();
//        String lock_entrust = userId+entrust.getPairs();
//        if(!member_entrust.containsKey(lock_entrust)){
//            member_entrust.put(lock_entrust, 1);
//        }else {
//            throw new BusinessException("操作频繁");
//        }
//        if(Strings.isBlank(entrust.getPairs())){
//            throw new BusinessException("请输入交易对");
//        }
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisRepository.getRedisTemplate());
        boolean lock = redisDistributedLock.lock(CacheConstants.MEMBER_ENTRUST_PAIRS_KEY +userId, 15000, 50, 100);
        if(lock){
            //member_entrust.remove(userId + entrust.getPairs());
            //查询交易对是否存在
            QueryWrapper<Pairs> queryWrapper =  new QueryWrapper<>();
            queryWrapper.eq("pairs_name", entrust.getPairs()).eq("state", CoinConstant.Coin_State.NORMAL);
            Pairs pairs = pairsMapper.selectOne(queryWrapper);
            if(pairs == null){
                redisDistributedLock.releaseLock(CacheConstants.MEMBER_ENTRUST_PAIRS_KEY + userId);
                throw new BusinessException("交易对不存在");
            }
            entrust.setPairsName(pairs.getPairsName());
            entrust.setMember(userId);
            entrust.setMainCur(pairs.getMainCur());
            entrust.setTokenCur(pairs.getTokenCur());
            entrust.setMemberType("people");
            Member member = memberMapper.selectById(entrust.getMember());
            //手续费
            if(member.getType() != null){
                if (member.getType().equals("INTERNAL")) {
                    entrust.setTradeRate(new BigDecimal("0"));
                } else {
                    entrust.setTradeRate(pairs.getTradeRate());
                }
            }else {
                entrust.setTradeRate(pairs.getTradeRate());
            }
            entrust.setUld("UP");
            String uuid = UUID.randomUUID().toString().replace("-", "");
            entrust.setId(uuid);
            try {
                sendEntrust(entrust,pairs);
            }finally {
                redisDistributedLock.releaseLock(CacheConstants.MEMBER_ENTRUST_PAIRS_KEY + entrust.getMember());
            }
        }else {
           // member_entrust.remove(userId + entrust.getPairs());
            throw new BusinessException("操作频繁!");
        }
        return true;
    }

    private void sendEntrust(Entrust entrust,Pairs pairs){
        log.info("entrust pairs {},{}",entrust,pairs);
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisRepository.getRedisTemplate());
        boolean lock_coin = redisDistributedLock.lock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember(),15000, 50, 100);
        try {
            if(lock_coin){
                QueryWrapper<Balance> queryWrapper =  new QueryWrapper<>();
                switch (entrust.getEntrustType().getType()){
                    case "BUY":
                        queryWrapper.eq("currency",pairs.getMainCur());
                        break;
                    case "SELL":
                        queryWrapper.eq("currency",pairs.getTokenCur());
                        break;
                }
                queryWrapper.eq("user_id",entrust.getMember());
                //查询余额
                Balance balance = balanceMapper.selectOne(queryWrapper);
                if(entrust.getPriceType().equals(ContractConstant.Price_Type.MARKET_PRICE)){
                    String result = redisRepository.get(CacheConstants.PRICE_HIG_LOW_KEY + pairs.getPairsName());
                    if(Strings.isEmpty(result)){
                        redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
                        throw new BusinessException("价格未获取!");
                    }
                    JSONObject jsonInfo = JSONObject.parseObject(result);
                    BigDecimal price = jsonInfo.getBigDecimal("nowPrice");
                    entrust.setPrice(price);
                    entrust.setUld("MARKET");
                    if(entrust.getEntrustType().equals(EntrustConstant.Entrust_Type.BUY)){
                        if(entrust.getMatchFee().compareTo(new BigDecimal("0"))< 1){
                            redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
                            throw new BusinessException("购买数量过少,请充值");
                        }
                        if(balance.getBalance().compareTo(entrust.getMatchFee())< 0){
                            redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
                            throw new BusinessException("余额不够");
                        }
                        //交易百分比 是否全部交易
                        if(entrust.getPercentageCount().compareTo(new BigDecimal("1"))==0){
                            BigDecimal count = balance.getBalance().divide(price, 8, RoundingMode.HALF_UP);
                            entrust.setCount(count);
                            balance.setBalance(new BigDecimal("0"));
                            balance.setBlockedBalance(balance.getBlockedBalance().add(balance.getBalance()));//冻结
                        }else {
                            BigDecimal count = entrust.getMatchFee().divide(price, 8, RoundingMode.HALF_UP);
                            entrust.setCount(count);
                            balance.setBalance(balance.getBalance().subtract(entrust.getMatchFee()));
                            balance.setBlockedBalance(balance.getBlockedBalance().add(entrust.getMatchFee()));//冻结
                        }
                    }else {
                        if(entrust.getCount().compareTo(new BigDecimal("0"))< 1){
                            redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
                            throw new BusinessException("交易数量大于0");
                        }
                        if(balance.getBalance().compareTo(entrust.getCount())< 0){
                            redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
                            throw new BusinessException("余额不够");
                        }

                        if(entrust.getPercentageCount().compareTo(new BigDecimal("1"))==0){
                            balance.setBlockedBalance(balance.getBlockedBalance().add(balance.getBalance()));
                            balance.setBalance(new BigDecimal("0"));
                        }else {
                            balance.setBalance(balance.getBalance().subtract(entrust.getCount()));
                            balance.setBlockedBalance(balance.getBlockedBalance().add(entrust.getCount()));
                        }
                    }
                    balanceMapper.updateById(balance);
                    //发送消息
//                if (pairs.getType().equals(CoinConstant.Coin_Type.MAIN_COIN)) {
//                    matchProducer.putMainEntrustMatch(JSONObject.toJSONString(entrust));
//                } else {
//                    matchProducer.putProjectEntrustMatch(JSONObject.toJSONString(entrust));
//                }
                    redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
                }else {
                    if(entrust.getCount().compareTo(new BigDecimal("0"))< 1){
                        throw new BusinessException("数量不能小于0");
                    }
                    if(entrust.getPrice().compareTo(new BigDecimal("0"))< 1){
                        throw new BusinessException("价格不能小于0");
                    }

                    entrust.setState(EntrustConstant.Order_State.CREATE);
                    if(entrust.getEntrustType().equals(EntrustConstant.Entrust_Type.BUY)){
                        BigDecimal sumPrice = entrust.getCount().multiply(entrust.getPrice());
                        if(balance.getBalance().compareTo(sumPrice)< 0){
                            throw new BusinessException("余额不足buy");
                        }
                        //冻结
                        if(entrust.getPercentageCount().compareTo(new BigDecimal("1"))==0){
                            entrust.setCount(balance.getBalance().divide(entrust.getPrice(), 8, RoundingMode.HALF_UP));
                            balance.setBalance(new BigDecimal("0"));
                            balance.setBlockedBalance(balance.getBlockedBalance().add(balance.getBalance()));
                        }else {
                            balance.setBalance(balance.getBalance().subtract(sumPrice));
                            balance.setBlockedBalance(balance.getBlockedBalance().add(sumPrice));
                        }
                        //entrust.setMatchFee(sumPrice);
                    }else {
                        if(balance.getBalance().compareTo(entrust.getCount())< 0){
                            throw new BusinessException("余额不足");
                        }
                        balance.setBalance(balance.getBalance().subtract(entrust.getCount()));
                        balance.setBlockedBalance(balance.getBlockedBalance().add(entrust.getCount()));
                    }
                    balanceMapper.updateById(balance);
                    entrust.setSurplusCount(entrust.getCount());
                    entrustMapper.insert(entrust);
                    //发送消息
                    if (pairs.getType().equals(CoinConstant.Coin_Type.MAIN_COIN)) {
                        matchProducer.putMainEntrustMatch(JSONObject.toJSONString(entrust));
                    } else {
                        matchProducer.putProjectEntrustMatch(JSONObject.toJSONString(entrust));
                    }
                }
            }else {
                //sendEntrust(entrust, pairs);
                throw new BusinessException("频繁稍后再试");
            }
        }finally {
            redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + entrust.getMember());
        }

    }

    public List<EntrustHistory> getHistoryEntrust(String pairsName){
         QueryWrapper<EntrustHistory> queryWrapper = new QueryWrapper<>();
         if(Strings.isNotEmpty(pairsName)){
             queryWrapper.eq("pairs_name",pairsName);
         }
        String MemberId = UserContextUtils.getCurrentUserId();
        queryWrapper.eq("member_id",MemberId);
        queryWrapper.orderByDesc("create_time");
        return entrustHistoryMapper.selectList(queryWrapper);
    }
}
